/**
 * Created by liuyaqi on 2017/4/8.
 */
//http://blog.csdn.net/star_dragon/article/details/50728972

function DBSCAN(D,eps,MinPts,size){//此处eps即为半径r，D是一维数组
    var C = 0;
    D.forEach(function(P){
        //数据示意：{point:{row:x,col:y},value:v,visited:0,cluster:0,type:0}, type:2噪声，
        P.visited = 1;
        var NeighborPts = regionQuery(P,eps,D,size);//查询p的邻域内的所有点
        if(NeighborPts.length<MinPts){
            P.type = 2;//非核心点标记为噪声，注意这并非最终结果，可能在后面被归入某一类成为边界点
        }else{
            C++;
            expandCluster(P,NeighborPts,C,eps,MinPts,D,size);//若是核心点，则扩展该类
        }
    });
}
function expandCluster(P, NeighborPts, C, eps, MinPts, D,size){
    P.cluster = C;
    //遍历邻域内所有点，查询其是否可以拓展类
    var length = NeighborPts.length;
    for(var i=0;i<length;i++){
        var P1 = NeighborPts[i];
        if(P1.visited === 0){
            P1.visited = 1;
            NeighborPts1 = regionQuery(P1, eps, D, size);
            if(NeighborPts1.length>=MinPts){//若是核心点，则其邻域内的点也要继续遍历
                NeighborPts = NeighborPts.concat(NeighborPts1);
                length = NeighborPts.length;
            }
        }
        if(P1.cluster === 0){//对邻域内的所有点，若尚未归类，则将其划入类C
            P1.cluster = C;
        }
    }
}
function regionQuery(P, eps, D, size){
    //在D中查询P的邻域内的所有满足条件的点
    var res = [];
    for(var i=P.point.row-eps;i<=P.point.row+eps;i++){
        if(i<0)continue;
        if(i>=size.row)break;
        for(var j=P.point.col-eps;j<=P.point.col+eps;j++){
            if(j<0)continue;
            if(j>=size.col)break;
            var tmp = D[i*size.col+j];
            //console.log(tmp.point,[i*size.row+j],tmp.id);
            //如果满足value大于0的条件，则加入数组
            if(!tmp){
                console.log("error");
                console.log("tmp",tmp);
                console.log("i",i,"j",j);
                console.log("i*size.col+j",i*size.col+j);
                console.log("D.length",D.length);
            }
            if(tmp.value>0){
                res.push(tmp);
            }
        }
    }
    return res;
}
//构造一条数据
function createOneData(i,j,v,id){
    return {point:{row:i,col:j},value:v,visited:0,cluster:0,type:0,id:id};
}
/************************************************************************/
const readline = require("readline");
const fs = require('fs');
//数据输出
function exportData(D){
    console.log("exportData");
    //console.log(D);
}
//从文本读数据
function readData(path,size){
    return new Promise(function(resolve,reject){
        var data = new Array(size.row*size.col);
        for(let index=0;index<data.length;index++){
            var i = Math.floor(index/size.col);
            var j = index - i*size.col;
            data[index] = createOneData(i,j,0,index+1);//id是从1开始
        }
        console.log("data length",data.length);
        console.log("data",data);
        const rl = readline.createInterface({
            input: fs.createReadStream(path)
        });
        rl.on('line', function(line){
            line = line.split(",").map(function(v){return parseInt(v);});
            var index = (line[1]-1)*size.col+(line[2]-1);
            //console.log(index,data[index]);
            console.log("line",line[0]);
            data[index].value = line[3];
        }).on('close', function(){
            console.log("line end");
            resolve(data);
        });
    });
}

const size = {row:2790,col:2545};
const eps = 5;
const MinPts = 15;

const path = "F:/2790行2545列.csv";

readData(path,size)
    .then(function(data){
        DBSCAN(data,eps,MinPts,size);
        exportData(data);
    })
    .catch(function(e){
        console.log("error",e);
    });
